// exception.cc 
//	Entry point into the Nachos kernel from user programs.
//	There are two kinds of things that can cause control to
//	transfer back to here from user code:
//
//	syscall -- The user code explicitly requests to call a procedure
//	in the Nachos kernel.  Right now, the only function we support is
//	"Halt".
//
//	exceptions -- The user code does something that the CPU can't handle.
//	For instance, accessing memory that doesn't exist, arithmetic errors,
//	etc.  
//
//	Interrupts (which can also cause control to transfer from user
//	code into the Nachos kernel) are handled elsewhere.
//
// For now, this only handles the Halt() system call.
// Everything else core dumps.
//
// Copyright (c) 1992-1993 The Regents of the University of California.
// All rights reserved.  See copyright.h for copyright notice and limitation 
// of liability and disclaimer of warranty provisions.

#include <stdio.h>        // FA98
#include <stdlib.h>
#include "copyright.h"
#include "system.h"
#include "syscall.h"
#include "addrspace.h"   // FA98
#include "sysdep.h"   // FA98
#include "directory.h" 
#include "list.h"
#include <vector.h>
// begin FA98

static int SRead(int addr, int size, int id);
static void SWrite(char *buffer, int size, int id);
Thread * getID(int toGet);
void Parse(char *filename);
void InnerParse(char *);





// end FA98

//----------------------------------------------------------------------
// ExceptionHandler
// 	Entry point into the Nachos kernel.  Called when a user program
//	is executing, and either does a syscall, or generates an addressing
//	or arithmetic exception.
//
// 	For system calls, the following is the calling convention:
//
// 	system call code -- r2
//		arg1 -- r4
//		arg2 -- r5
//		arg3 -- r6
//		arg4 -- r7
//
//	The result of the system call, if any, must be put back into r2. 
//
// And don't forget to increment the pc before returning. (Or else you'll
// loop making the same system call forever!
//
//	"which" is the kind of exception.  The list of possible exceptions 
//	are in machine.h.
//----------------------------------------------------------------------
int info = NULL;
bool valid;
char **tokenname = new char*[5];
int CDcounter = 0;
bool flag=true;
char *file;
bool loc = false;
const int ROOT = 1;

std::vector<int> CDList;
std::vector<int> DList;

/*!Variable for ls or ls -l */
Thread* getID(int toGet)	// Goes through the list of active threads and returns one linked with the passed-in ID.
{
	Thread * tempThread = NULL;
	Thread * toReturn = NULL;
	bool found = false;
	int size = activeThreads->getSize();
	for(int i = 0; i < size; i++)
	{
		tempThread = (Thread*)activeThreads->Remove();	// Pop the top thread off.
		if (tempThread->getID() == toGet)	// If it's what we're looking for...
		{
			toReturn = tempThread;
			found = true;	// Trip the flag variable, and store the pointer of the thread.
		}
		activeThreads->Append(tempThread);	// Put it back onto the active list.
	}
	if (!found)
		return NULL;
	else return toReturn;
}
	
void processCreator(int arg)	// Used when a process first actually runs, not when it is created.
 {
	currentThread->space->InitRegisters();		// set the initial register values
    currentThread->space->RestoreState();		// load page table register
	
	if (threadToBeDestroyed != NULL){
		delete threadToBeDestroyed;
		threadToBeDestroyed = NULL;
	}

    machine->Run();			// jump to the user progam
    ASSERT(FALSE);			// machine->Run never returns;
 }

void
ExceptionHandler(ExceptionType which)
{
	int type = machine->ReadRegister(2);

	int arg1 = machine->ReadRegister(4);
	int arg2 = machine->ReadRegister(5);
	int arg3 = machine->ReadRegister(6);
	int Result;
	int i, j;
	char *ch = new char [500];

	switch ( which )
	{
	case NoException :
		break;
	case SyscallException :

		// for debugging, in case we are jumping into lala-land
		// Advance program counters.
		machine->registers[PrevPCReg] = machine->registers[PCReg];
		machine->registers[PCReg] = machine->registers[NextPCReg];
		machine->registers[NextPCReg] = machine->registers[NextPCReg] + 4;

		switch ( type )
		{

		case SC_Halt :
			//printf("SYSTEM CALL: Halt, called by thread %i.\n",currentThread->getID());
			DEBUG('t', "Shutdown, initiated by user program.\n");
			interrupt->Halt();
			break;

			
		case SC_Read :
			if (arg2 <= 0 || arg3 < 0){
				printf("\nRead 0 byte.\n");
			}
			Result = SRead(arg1, arg2, arg3);
			machine->WriteRegister(2, Result);
			DEBUG('t',"Read %d bytes from the open file(OpenFileId is %d)",arg2, arg3);
			break;

		case SC_Write :
			for (j = 0; ; j++) {
				if(!machine->ReadMem((arg1+j), 1, &i))
					j=j-1;
				else{
					ch[j] = (char) i;
					if (ch[j] == '\0') 
						break;
				}
			}
			if (j == 0){
				printf("\nWrite 0 byte.\n");
				// SExit(1);
			} else {
				DEBUG('t', "\nWrite %d bytes from %s to the open file(OpenFileId is %d).", arg2, ch, arg3); //printf("entering SWrite \n");
				SWrite(ch, j, arg3);
			}
			break;  
		case SC_Exec :	// Executes a user process inside another user process.
		   {
				valid = true;
				//printf("SYSTEM CALL: Exec, called by thread %i.\n",currentThread->getID());

				// Retrieve the address of the filename
				int fileAddress = arg1; // retrieve argument stored in register r4
				//bool cmd = true;
				// Read file name into the kernel space
				char *filename = new char[100];
				char *command = new char[100];
				for(int m = 0; m < 100; m++) {
					filename[m] = NULL;
					command[m]=NULL;
				}
				// Free up allocation space and get the file name
				if(!machine->ReadMem(fileAddress,1,&j))return;
				i = 0;
				while(j != 0)
				{

						filename[i]=(char)j;
						fileAddress += 1;
						i++;
						if(!machine->ReadMem(fileAddress,1,&j))return;
					
				}
				// Open File
				filename = strtok(filename, "\n");
				
				if (filename == NULL)
					break;
				
					
				if (flag==true)
				{
  					CDList.insert (CDList.begin(), 1 );
					flag=false;
				}
				
				//printf("Filename is*%s.\n", filename);
				Parse(filename);
				command = strtok(filename, " ");
					
				if (valid)
					break;
					
				OpenFile *executable = fileSystem->OpenRt(command);
				if (executable == NULL) 
				{
					printf("Command: %s not found!\n", command);
					delete filename;
					break;
				}
				delete filename;
				

				// Calculate needed memory space
				AddrSpace *space;
				space = new AddrSpace(executable);
				delete executable;
				// Do we have enough space?
				if(!currentThread->killNewChild)	// If so...
				{
					Thread* execThread = new Thread("thrad!");	// Make a new thread for the process.
					execThread->space = space;	// Set the address space to the new space.
					execThread->setID(threadID);	// Set the unique thread ID
					activeThreads->Append(execThread);	// Put it on the active list.
					machine->WriteRegister(2, threadID);	// Return the thread ID as our Exec return variable.
					threadID++;	// Increment the total number of threads.
					execThread->Fork(processCreator, 0);	// Fork it.
				}
				else	// If not...
				{
					machine->WriteRegister(2, -1 * (threadID + 1));	// Return an error code
					currentThread->killNewChild = false;	// Reset our variable
				}
				
				break;	// Get out.
				
			}
			case SC_Join :	// Join one process to another.
			{
				//printf("SYSTEM CALL: Joined, called by thread %i.\n",currentThread->getID());
				if(arg1 < 0)	// If the thread was not properly created...
				{
					//printf("ERROR: Trying to join process %i to process %i, which was not created successfully! Process %i continuing normally.\n", currentThread->getID(), -arg1, currentThread->getID());	// Return an error message, continue as normal.
					break;
				}
				
				if(getID(arg1) != NULL)	// If the thread exists...
				{
					if(!currentThread->isJoined)	// And it's not already joined...
					{
						//printf("Joining process %i with process %i.  Thread %i now shutting down.\n", getID(arg1)->getID(), currentThread->getID(), currentThread->getID());	// Inform the user.
						getID(arg1)->setParent(currentThread);	// Set the process' parent to the current thread.
						currentThread->isJoined = true;	// Let the parent know it has a child
						(void) interrupt->SetLevel(IntOff);	// Disable interrupts for Sleep();
						currentThread->Sleep();	// Put the current thread to sleep.
						break;
					}
					else{	// We've got an error message.
						//printf("ERROR: Trying to join prargsocess %i, which is already joined! Continuing normally.", currentThread->getID());
						break;
						}
				}
				//else printf("ERROR: Trying to a join process %i to nonexistant process %i! Process %i continuing normally.\n", currentThread->getID(), -arg1, currentThread->getID());	// Error message if the thread we're trying to join to doesn't exist for some reason.
				break;
			}
			case SC_Exit :	// Exit a process.
			{
				//printf("SYSTEM CALL: Exit, called by thread %i.\n",currentThread->getID());
				/*if(arg1 == 0)	// Did we exit properly?  If not, show an error message.
					printf("Process %i exited normally!\n", currentThread->getID());
				else
					printf("ERROR: Process %i exited abnormally!\n", currentThread->getID());
				*/
				if(currentThread->space)	// Delete the used memory from the process.
					delete currentThread->space;
				currentThread->Finish();	// Delete the thread.

				break;
			}
           case SC_Yield :	// Yield to a new process.
		   {
			   //printf("SYSTEM CALL: Yield, called by thread %i.\n",currentThread->getID());

			   //Save the registers and yield CPU control.
			   currentThread->space->SaveState();
			   currentThread->Yield();
			   //When the thread comes back, restore its registers.
			   currentThread->space->RestoreState();

               break;
			}

	case SC_Create:
		{
		//printf("SYSTEM CALL: CREATE, called by thread %i.\n",currentThread->getID());
		int fileAddress = arg1; // retrieve argument stored in register r4

		// Read file name into the kernel space
		char *filename = new char[100];
				
		for(int m = 0; m < 100; m++)
		filename[m] = NULL;

		// Free up allocation space and get the file name
		if(!machine->ReadMem(fileAddress,1,&j))return;
		i = 0;

		while(j != 0)
		{
			filename[i]=(char)j;
			fileAddress += 1;
			i++;
		if(!machine->ReadMem(fileAddress,1,&j))return;
		}
		fileSystem->Create(filename, arg2);
		printf("arg1 = %s arg2 = %d \n", filename, arg2);
	
		break;
		}

	case SC_Open:
	{
		//printf("SYSTEM CALL: OPEN, called by thread %i.\n",currentThread->getID());
//stuff that reads out of arg1 and makes it a char * thing
		int fileAddress = arg1; // retrieve argument stored in register r4
		// Read file name into the kernel space
		char *filename = new char[100];
			
		for(int m = 0; m < 100; m++)
		filename[m] = NULL;

		// Free up allocation space and get the file name
		if(!machine->ReadMem(fileAddress,1,&j))return;
		i = 0;

		while(j != 0)
		{
			filename[i]=(char)j;
			fileAddress += 1;
			i++;
		if(!machine->ReadMem(fileAddress,1,&j))return;
		}
//------------------------------------------------------------------end of char* thing which is filename
		fileYname * openFile = new fileYname;
		openFile->name = filename;
		openFile->file = fileSystem->Open(filename);
		openFile->id = ofcount++;
		oflist->Append(openFile);
		break;
	}
	case SC_Close:
	{
		//printf("SYSTEM CALL: CLOSE, called by thread %i.\n",currentThread->getID());
		if(oflist->getSize() == 0)
		{
			printf("No open files exist!!!! \n");
		}
		for(int k = oflist->getSize(); k > 0; k--)
		{
			fileYname * rfile = ((fileYname *) oflist->Remove());
			if(rfile->id == arg1)
			{
				//printf("closing open file : %s \n", rfile->name);
				delete rfile;	//close the file via openfile destructor!!!!
				break;
			}
			else
			{
				//printf("not closing open file : %s \n", rfile->name);
				oflist->Append(rfile);	//this is not the file, put it back!!!!
			}
		}
	// delete filename;
		break;
	}
           default :
	       //Unprogrammed system calls end up here
			  // printf("SYSTEM CALL: Unknown, called by thread %i.\n",currentThread->getID());
               break;
           }         // Advance program counters, ends syscall switch
           break;

	case ReadOnlyException :
		printf("ERROR: ReadOnlyException, called by thread %i.\n",currentThread->getID());
		if (currentThread->getName() == "main")
			ASSERT(FALSE);  //Not the way of handling an exception.
		if(currentThread->space)	// Delete the used memory from the process.
			delete currentThread->space;
		currentThread->Finish();	// Delete the thread.
		break;
	case BusErrorException :
		printf("ERROR: BusErrorException, called by thread %i.\n",currentThread->getID());
		if (currentThread->getName() == "main")
			ASSERT(FALSE);  //Not the way of handling an exception.
		if(currentThread->space)	// Delete the used memory from the process.
			delete currentThread->space;
		currentThread->Finish();	// Delete the thread.
		break;
	case AddressErrorException :
		printf("ERROR: AddressErrorException, called by thread %i.\n",currentThread->getID());
		if (currentThread->getName() == "main")
			ASSERT(FALSE);  //Not the way of handling an exception.
		if(currentThread->space)	// Delete the used memory from the process.
			delete currentThread->space;
		currentThread->Finish();	// Delete the thread.
		break;
	case OverflowException :
		printf("ERROR: OverflowException, called by thread %i.\n",currentThread->getID());
		if (currentThread->getName() == "main")
			ASSERT(FALSE);  //Not the way of handling an exception.
		if(currentThread->space)	// Delete the used memory from the process.
			delete currentThread->space;
		currentThread->Finish();	// Delete the thread.
		break;
	case IllegalInstrException :
		printf("ERROR: IllegalInstrException, called by thread %i.\n",currentThread->getID());
		if (currentThread->getName() == "main")
			ASSERT(FALSE);  //Not the way of handling an exception.
		if(currentThread->space)	// Delete the used memory from the process.
			delete currentThread->space;
		currentThread->Finish();	// Delete the thread.
		break;
	case NumExceptionTypes :
		printf("ERROR: NumExceptionTypes, called by thread %i.\n",currentThread->getID());
		if (currentThread->getName() == "main")
			ASSERT(FALSE);  //Not the way of handling an exception.
		if(currentThread->space)	// Delete the used memory from the process.
			delete currentThread->space;
		currentThread->Finish();	// Delete the thread.
		break;

		default :
		//      printf("Unexpected user mode exception %d %d\n", which, type);
		//      if (currentThread->getName() == "main")
		//      ASSERT(FALSE);
		//      SExit(1);
		break;
	}
	delete [] ch;
}


static int SRead(int addr, int size, int id)  //input 0  output 1
{
	char buffer[size+10];
	int num,Result;
	//printf("In Sread \n");
	//read from keyboard, try writing your own code using console class.
	if (id == 0)
	{
		fgets(buffer, size, stdin);
		//printf("Buffer is %s.\n", buffer);
		num=strlen(buffer); //set num equal to length of the buffer
		if(num>(size+1)) {

			buffer[size+1] = '\0';
			Result = size+1;
		}
		else {
			buffer[num+1]='\0';
			Result = num + 1;
		}

		for (num=0; num<Result; num++)
		{  machine->WriteMem((addr+num), 1, (int) buffer[num]);
			if (buffer[num] == '\0')
			break; }
		return num;

	}
	//read from a unix file, later you need change to nachos file system.
	else	//read a file
	{	
		//First, find the file that we want to read from in the oflist
		fileYname * rfile;
		if(oflist->getSize() == 0)
		{
			printf("No open files exist!!!! \n");
			return -1;
		}
		for(int k = oflist->getSize(); k > 0; k--)
		{
			rfile = ((fileYname *) oflist->Remove());
			if(rfile->id == id)
			{
				//We got the file
				break;
			}
			else
			{
				//printf("not closing open file : %s \n", rfile->name);
				oflist->Append(rfile);	//this is not the file, put it back!!!!
				if(k == 1)
				{
					printf("No file open matching id \n");
					return -1;
				}
			}
		}
		//Now that rfile has the file we want to read, we shall commence reading
		//Not so confident about this part
		for(num=0;num<size;num++){
			rfile->file->Read(&buffer[num],1);
			machine->WriteMem((addr+num), 1, (int) buffer[num]);
			if(buffer[num]=='\n') break;
		}
		oflist->Append(rfile);	//put it back cuz it still open
		return num;		//returns the number of bytes read
	}
}



static void SWrite(char *buffer, int size, int id)
{
	//int * addr;
	fileYname * rfile;
	//write to terminal, try writting your own code using console class.
	//printf("inSWrite before if id == 1 id = %d\n" , id);
	if (id == 1)
	printf("%s", buffer);
	//write to a unix file, later you need change to nachos file system.
	if (id >= 2)
	{
		//printf("inSWrite after if id >= 2 \n");
		//First, find the file that we want to read from in the oflist

		if(oflist->getSize() == 0)
		{
			printf("No open files exist!!!! ahhhh\n");
			return;
		}
		for(int k = oflist->getSize(); k > 0; k--)
		{
			rfile = ((fileYname *) oflist->Remove());
			if(rfile->id == id)
			{
				//We got the file
				break;
			}
			else
			{
				//printf("not closing open file : %s \n", rfile->name);
				oflist->Append(rfile);	//this is not the file, put it back!!!!
				if(k == 1)
				{
					printf("No file open matching id \n");
					return;
				}
			}
		}
		//Now that we have the file, we can write to it
		rfile->file->Write(buffer,size);
		oflist->Append(rfile);	//put it back cuz it still open
	}
}

int Locate(char* path)
{
	int dirCount = 0;
	int sizeBytes;
	char* last = strrchr(path, 47); //Find last occurance of "/"
	char* end = strchr(path, 0); //Find the end of line char
	char* first = strchr(path, 47);
	int sector;
	int prev;
	char *dir = strtok(path, "/");
	if (first == &path[0])
	{
		fileSystem->currentdir = ROOT;	
	}
	file = ++last;
		while ((int)dir != 0)
		{
			if (strcmp(".", dir) == 0)
			{
				prev = fileSystem->currentdir;
				info = 1;
			}
			else if (strcmp("..", dir) == 0)
			{
				info = 2;
				prev = fileSystem->currentdir;
				Change_dir();
			}
			else
			{
				prev = fileSystem->currentdir;
				info = 3;
				//Change_dir();
			}
			if (dir+2 == file) //!So dir will hold the previous directory and not the file
				break;
			dir = strtok(NULL, "/");
		}
		//printf("Dir is %s \n", dir);

				OpenFile* currentopendir = new OpenFile(fileSystem->currentdir); 
				sizeBytes = currentopendir->Length();
		
				//fetches whatever is in the current directory
				Directory *directory = new Directory((sizeBytes/sizeof(DirectoryEntry)));
				directory->FetchFrom(currentopendir);
				if (!loc) {
					sector = directory->Find(file);//finds the sector of the current dir
					return sector; 
				}
				else
				{
					//printf("here \n");
					return prev; //return directory that you want to copy to
				}

}

void InnerParse(char *stri)
{
	vector<int> DList(CDList);
	vector<int>::iterator Iter;


	for (Iter = DList.begin(); Iter < DList.end();Iter++)
		printf("%d",*Iter);

	char **tokendirname = new char*[3];
	char *tokendirch = NULL;
  	

  	int i;
  	int dircount=0;
  	int dirArgCount = 3;
  	int sizeBytes;
  		
  	for (i =0;i<dirArgCount;i++)
  		tokendirname[i]=NULL;
  	
  	tokendirch = strtok (stri,"/");
  	
  	while (tokendirch != NULL && dircount<dirArgCount)
  	{
    		tokendirname[dircount]= tokendirch;
    		tokendirch = strtok (NULL, "/");
    		dircount++;
  	}
  	
  	for (i = 0; i<dirArgCount; i++)
  		printf("\n%s",tokendirname[i]);
  		
  	if (strcmp(tokendirname[0], "..") == 0)
		{
	
		DList.pop_back();
		fileSystem->currentdir = 1;
		for (Iter = DList.begin(); Iter < DList.end();Iter++)
		{	
			OpenFile* currentopendir = new OpenFile(fileSystem->currentdir); 
			sizeBytes = currentopendir->Length();
	
			//fetches whatever is in the current directory
			Directory *directory = new Directory((sizeBytes/sizeof(DirectoryEntry)));
			directory->FetchFrom(currentopendir);
		
			fileSystem->currentdir = *Iter;
				
			delete directory;
			delete currentopendir;	
				
		}
		}
	else if (strcmp(tokendirname[0], ".") == 0)
		{
		}
			int sector;
			
			for (i = 1; i<dirArgCount; i++)
			{
			BitMap* dirmap = new BitMap(NumSectors);
        		OpenFile* dirmapopen = new OpenFile(2);
        		dirmap->FetchFrom(dirmapopen);
	
			OpenFile* currentopendir = new OpenFile(fileSystem->currentdir); 
			sizeBytes = currentopendir->Length();
	
			//fetches whatever is in the current directory
			Directory *directory = new Directory((sizeBytes/sizeof(DirectoryEntry)));
			directory->FetchFrom(currentopendir);
	
			sector = directory->Find(tokendirname[i]);
	
			if(sector !=-1 && dirmap->Test(sector))
			{
				fileSystem->currentdir = sector; 
			}
			else
			{
				printf("\nCould not find the directory: %s\n", tokendirname[i]);
				break;
			}
			delete directory;
			delete currentopendir;	
			delete dirmap;
			delete dirmapopen;		
			}
			
}


void Parse(char *str)
{

	//!Need to copy the file name 
	//strcpy(command, filename);
	//strcpy(line, command);
	
	if (str == NULL)
	{
	}
	else
	{
	
	char *tokench = NULL;
  	
  	
  	int i;
  	int argcount=0;
  		
  	for (i =0;i<5;i++)
  		tokenname[i]=NULL;
  	
  	tokench = strtok (str," ");
  	
  	while (tokench != NULL && argcount<5)
  	{
    		tokenname[argcount]= tokench;
    		tokench = strtok (NULL, " ");
    		argcount++;
  	}
  	
	//the comparision of command with tokenname[0] which holds the command name
	if (strcmp(tokenname[0],"ls") == 0)
	{
		/*!Returns pointer to characters after and including the first hyphen.*/
		if (argcount==1)
		{
			Ls();
		}
		else if (argcount==2)
		{
			if (strcmp(tokenname[1], "-l") == 0)
			{
				info = 1;
				Ls();
			}
			else 
			{
				printf("Command unrecognized. \n");
				valid = false;
			}
		}
		else
		{
			printf("Command unrecognized. \n");
			valid = false;
		}
		

	}
	else if (strcmp(tokenname[0], "pwd") == 0)
	{
		Pwd();
	}
	else if (strcmp(tokenname[0], "cat") == 0)
	{
		//printf("Command is cat. \n");
		if (strcmp(tokenname[0], "cat"))
		{
			printf("Invalid number of arguments. \n");
			valid = false;
		}
		
	}
	else if (strcmp(tokenname[0], "mkdir") == 0)
	{
		if (argcount == 1)
		{
			printf("Less Arguments! \n");
			valid = false;
		}
		else if (argcount>=2)
		{	
			Make_dir();
		}
		else 
		{
			printf("Command unrecognized. \n");
			valid = false;
		}

	}
	else if (strcmp(tokenname[0], "rmdir") == 0)
	{ 
		if (argcount == 1)
		{
			printf("Less Arguments! \n");
			valid = false;
		}
		else if (argcount>=2)
		{	
			Remove_dir();
		}
		else 
		{
			printf("Command unrecognized. \n");
			valid = false;
		}
		
	}
	else if (strcmp(tokenname[0], "rm") == 0)
	{	
		if (argcount == 1)
		{
			printf("Less Arguments! \n");
			valid = false;
		}
		else if (argcount>=2)
		{	
			Remove();
		}
		else 
		{
			printf("Command unrecognized. \n");
			valid = false;
		}
	}
	else if (strcmp(tokenname[0], "mv") == 0)
	{
		if (strcmp(tokenname[0], "mv") == 0 && argcount < 2)
		{
			printf("Invalid number of arguments. \n");
			valid = false;
		}
	}
	else if (strcmp(tokenname[0], "cp") == 0)
	{	
		if (strcmp(tokenname[0], "cp") == 0 && argcount < 3)
		{	
			printf("Invalid number of arguments. \n");
			valid = false;
		}
		else
		{
			Copy();
		}
		
	}
	else if (strcmp(tokenname[0], "cd") == 0)
	{
		if (argcount == 1)
			{
				printf("Less Arguments. \n");
				valid = false;
			}
		else if (argcount>=2)
		{	
			if (strcmp(tokenname[1], ".") == 0)
			{	
				info = 1;
				Change_dir();
			}
			else if (strcmp(tokenname[1], "..") == 0)
			{	
			
				fileSystem->currentdir = 1; 
				info = 2;
				Change_dir();
			}
			else if (strcmp(tokenname[1], "/") == 0)
			{	
				fileSystem->currentdir = 1; 
				CDList.erase(CDList.begin(), CDList.end());
				CDList.insert (CDList.begin(), 1 );
				info = 2;
			}
			else if (strcmp(tokenname[1], "../nakul/ryan") == 0)
			{
				InnerParse(tokenname[1]);
				printf("\n\n%d",fileSystem->currentdir);
			}/*
			else if ((strcmp(tokenname[1], "..") != 0) ||(strcmp(tokenname[1], ".") != 0))
			{
			info = 3;
			Change_dir();
			}*/
		}
		else 
		{
			printf("\nCommand unrecognized. \n");
			valid = false;
		}
	}
	else 
	{
		valid = false;
	}
}
}

void Pwd()
{
 vector<int>::iterator Iter;
 int savesector = fileSystem->currentdir;
 int sizeBytes = 0; 
 
 if (CDList.size()==1)
		{
			printf("/\n");
		}
 else
{
fileSystem->currentdir = 1;
for (Iter = CDList.begin(); Iter < CDList.end();Iter++)
	{	
		
			OpenFile* currentopendir = new OpenFile(fileSystem->currentdir); 
			sizeBytes = currentopendir->Length();
	
			//fetches whatever is in the current directory
			Directory *directory = new Directory((sizeBytes/sizeof(DirectoryEntry)));
			directory->FetchFrom(currentopendir);
			
			directory->PrintNameOfSector(*Iter);
			printf("/");
			
			fileSystem->currentdir = *Iter;
			
			delete directory;
			delete currentopendir;			
	}
	printf("\n");
}
	
	
	fileSystem->currentdir = savesector; 
}

void Ls()
{	
	int sizeBytes;
	
	OpenFile* currentopendir = new OpenFile(fileSystem->currentdir); 
	sizeBytes = currentopendir->Length();
 
	Directory *directory = new Directory((sizeBytes/sizeof(DirectoryEntry)));
	directory->FetchFrom(currentopendir);
		
	if(info==1)
		{
		directory->ListSize();
		info = 0;
		}
 	else 
 		directory->List();
 		
	delete directory;
	delete currentopendir;
}

// end FA98

void Make_dir()
{	printf("\nInside make dir\n");	
	
	int sector;	
	int sizeBytes;
	
	
	Directory *newdirectory = new Directory(12);
        BitMap* dirmap = new BitMap(NumSectors);
        
        //opening the current directory for fetch and write
        OpenFile* dirmapopen = new OpenFile(2);
        
        //fetching from the disk sector
        dirmap->FetchFrom(dirmapopen);
	
	//if create is SUCCESFUL then
	 //creates a file and saves it to the hardisk and stores the fileheader info in the current directory.
	if (!fileSystem->Create(tokenname[1], 12* sizeof(DirectoryEntry)))
		{printf("\nCould not create directory! Wrong path or filename\n");}
	else
	{
		// the current directory stores the sector number that contains the fileheader
		OpenFile* currentopendir = new OpenFile(fileSystem->currentdir); 
		sizeBytes = currentopendir->Length(); //length returns the size of the directory table.
	
		Directory *directory = new Directory((sizeBytes/sizeof(DirectoryEntry)));
		directory->FetchFrom(currentopendir);
		
		sector = directory->Find(tokenname[1]);//finds the sector of the current dir
		printf("MKDIR sector : %d\n",sector);
		dirmap->Mark(sector);//marks that sector as a directory
	
		OpenFile* opennewdir = new OpenFile(sector); //opening the newdirectory fileheader 
		newdirectory->WriteBack(opennewdir);//writing the directory to the sector that is pointed by the opened file header 
		dirmap->WriteBack(dirmapopen); //updating the dirmap in the hard disk.
		
		printf("\nDirectory: %s Created\n", tokenname[1]); 
		
		delete directory;
		delete dirmapopen;
		delete currentopendir;
		delete opennewdir;
	}
	delete newdirectory;
	delete dirmap;
	
	
}

void Remove_dir()
{	printf("\nInside remove dir\n");	

	BitMap* dirmap = new BitMap(NumSectors);
	
	//opening the current directory for fetch and write
    OpenFile* dirmapopen = new OpenFile(2);
	//fetching from the disk sector
    dirmap->FetchFrom(dirmapopen);
		
	int sizeBytes;
	int sector;
	
	//opens the current directory	
	OpenFile* currentopendir = new OpenFile(fileSystem->currentdir); 
	sizeBytes = currentopendir->Length();
 
 	//fetches whatever is in the current directory
	Directory *directory = new Directory((sizeBytes/sizeof(DirectoryEntry)));
	directory->FetchFrom(currentopendir);
	
	sector = directory->Find(tokenname[1]);//finds the sector of the current dir
	OpenFile* rmFile = new OpenFile(sector);
	if (dirmap->Test(sector)== 1 && rmFile->Length > 0)
	{
		if(fileSystem->Remove(tokenname[1]))
			printf("\nDirectory: %s Removed\n", tokenname[1]);
		else
			printf("\nCould not find directory: %s\n", tokenname[1]);
	}
	else
		printf("\nCould not find directory or direcotry not empty: %s\n", tokenname[1]);
	delete directory;
	delete currentopendir;	
}

void Change_dir()
{	
	printf("\nInside change dir\n");	
	if (info ==1)
	{
		info =0;
	}
	else if (info ==2)
	{	
		vector<int>::iterator Iter;
 		int sizeBytes;
 		
 		if (CDList.size()==1)
		{
			printf("\nYou are in the root. Cannot go back.\n");
		}
		else
		{
			CDList.pop_back();

			fileSystem->currentdir = 1;
			for (Iter = CDList.begin(); Iter < CDList.end();Iter++)
			{	
		
				OpenFile* currentopendir = new OpenFile(fileSystem->currentdir); 
				sizeBytes = currentopendir->Length();
	
				//fetches whatever is in the current directory
				Directory *directory = new Directory((sizeBytes/sizeof(DirectoryEntry)));
				directory->FetchFrom(currentopendir);
		
				fileSystem->currentdir = *Iter;
				
				delete directory;
				delete currentopendir;			
			}
		}
		info =0;
	}
	else if (info ==3)
	{	
		int sizeBytes;
		int sector;
	
		BitMap* dirmap = new BitMap(NumSectors);
        	OpenFile* dirmapopen = new OpenFile(2);
        	dirmap->FetchFrom(dirmapopen);
	
		OpenFile* currentopendir = new OpenFile(fileSystem->currentdir); 
		sizeBytes = currentopendir->Length();
	
		//fetches whatever is in the current directory
		Directory *directory = new Directory((sizeBytes/sizeof(DirectoryEntry)));
		directory->FetchFrom(currentopendir);
	
		sector = directory->Find(tokenname[1]);
	
		if(sector !=-1 && dirmap->Test(sector))
		{
			fileSystem->currentdir = sector; 
			CDList.push_back(sector);		
		}
		else
		{
			printf("\nCould not find the directory: %s\n", tokenname[1]);
		}
			
		delete directory;
		delete currentopendir;	
		delete dirmap;
		delete dirmapopen;
		info =0;
	}

}

void Remove()
{	printf("\nInside Remove file function\n");	
	
	BitMap* dirmap = new BitMap(NumSectors);
	
	//opening the current directory for fetch and write
    OpenFile* dirmapopen = new OpenFile(2);
	//fetching from the disk sector
    dirmap->FetchFrom(dirmapopen);
		
	int sizeBytes;
	int sector;
	
	//opens the current directory	
	OpenFile* currentopendir = new OpenFile(fileSystem->currentdir); 
	sizeBytes = currentopendir->Length();
 
 	//fetches whatever is in the current directory
	Directory *directory = new Directory((sizeBytes/sizeof(DirectoryEntry)));
	directory->FetchFrom(currentopendir);
	
	sector = directory->Find(tokenname[1]);//finds the sector of the current dir
	OpenFile *rmFile = new OpenFile(sector);
	for (int i=itr.begin(); i<itr.end(); ++i)
	{
		if (itr.
	}
	if (dirmap->Test(sector)== 0)
	{
		if(fileSystem->Remove(tokenname[1]))
			printf("\nFile: %s Removed\n", tokenname[1]);
		else
			printf("\nCould not find file: %s in the directory\n", tokenname[1]);
	}
	else
		printf("\nCould not find file: %s in the directory or this directory is not empty. \n", tokenname[1]);
		
	delete directory;
	delete currentopendir;	
}


void Copy()
{ 
	int start = fileSystem->currentdir;
	int sector1;
	int sector2;
	loc = false;
	
	BitMap* dirmap = new BitMap(NumSectors);
    	OpenFile* dirmapopen = new OpenFile(2);
    	dirmap->FetchFrom(dirmapopen);
	
	sector1 = Locate(tokenname[1]);
	printf("Sector of file is %d \n", sector1);
	loc = true;
	bool created;
	sector2 = Locate(tokenname[2]);
	printf("Sector of directory is %d \n", sector2);
	if (sector1 == -1 || sector2 == -1)
		printf("File not found. \n");
	else
	{
		//Check if file is a directory or not
		int sizeBytes;
		int sizeFile;
	
	//opens the current directory	
		OpenFile* currentopendir = new OpenFile(sector2); 
		sizeBytes = currentopendir->Length();

	//gets file
		OpenFile* target = new OpenFile(sector1);
		sizeFile = target->Length();
 	//fetches whatever is in the current directory
			Directory *directory = new Directory((sizeBytes/sizeof(DirectoryEntry)));
			directory->FetchFrom(currentopendir);
			created = fileSystem->Create(file, sizeFile);
			
			if (created == false)
				printf("Something went wrong. \n");
			else
			{
				printf("Attempting copy. \n");
				char *buffer = new char[sizeBytes];
				OpenFile* dest = fileSystem->Open(file);
				for (int i=0; i<sizeBytes; i++)
				{
					target->Read(buffer, 1);
					dest->Write(buffer, 1);
						
				} 
				printf("File created . \n");
			}
	}
	fileSystem->currentdir = start;
}

